#ifndef BIGQ_H
#define BIGQ_H
#include <pthread.h>
#include <iostream>
#include <cstdlib>
#include <queue>
#include <deque>
#include <string.h>
#include "Pipe.h"
#include "File.h"
#include "Record.h"
#include "TwoWayList.cc"



using namespace std;



class BigQ {

private:
	 class Compare{
	 public:
		 bool operator() (Record* left, Record* right);
		 OrderMaker orderBy;
		 Compare();
		 Compare(OrderMaker &sort);
		 virtual ~Compare();
	 };


	 // DBFile entities
	 File file;
	 Page *tempPage;
	 char *location;

     // Responsible for doing all the work...
	 pthread_t workerThread;
	 // Thread's status
     int threadStatus;

	 // Passed in values from the constructor. Main objects used in workerThread
     Pipe *in;
     Pipe *out;
     OrderMaker sortOrder;
     int runLength;

     ComparisonEngine engine;

     // Keeps count of current number of pages in our file. Must not exceed
     int pageNum;

     int numPages;
     // Keeps track of our page size, so as to not go over
     size_t currentPageSize;
     //

     TwoWayList <Record> *tempList;

     priority_queue<Record*, deque<Record*>, Compare > *sorter;

     // Assigns these objects to the BigQ for multiThreaded use
     void InitArgs(Pipe &inPipe, Pipe &outPipe, OrderMaker &sort, int runlen);
     void InitArgs(OrderMaker &sort, int runlen);
     // This is the sorting routine for the worker thread
     void *SortRoutine();
     // Input routine for worker thread: Grabs records from input pipe and blocks if unavailable.
	 // Stays in this routine until the pipe is shutdown
     void * InputRoutine();
     // Output routine for worker thread: shoves records to output pipe
     void * OutputRoutine();
     // Adds records from the temporaryList to the DiskPage
     void AddFromListToPage();
     // Adds DiskPage to the DBFile and then flashes the tempPage for reuse
     void AddPageAndSetup();
     // Returns a 1 if the bits will fit within the current page, and 0 if they wont
     int BitsWillFitPage(char * bits);
     // Returns a 1 if the list isn't empty, and a 0 if it is
     int TempListIsntEmpty();
     // Insert into a PageList in a sorted fashion
     void SortedPageInsert(Record &record);
     // Check to see if we are unable to insert the record in the current position of the list
     int CantInsertHere(Record &current);
     // Compare the current pageList Record with our record for insertion.
     // Returns 0 if good and 1 if bad
     int CompareCurrent(Record &record);
     // Overall Error Handling function for BigQ.
     void HandleError(int errorType);

     void SortingSetup();



     int CanGrabRecordFromPage(Record *record);

     Record *ConstToNonConst(const Record *o);


public:
     BigQ();
     BigQ(OrderMaker &sortOrder, int runlen);
     BigQ (Pipe &in, Pipe &out, OrderMaker &sortorder, int runlen);

     ~BigQ ();

     //This is the main thread routine, calls InputRoutine and OutputRoutine
     void *run();
     void AddToPipe(Record *record);
     void CloseInPipe();
     void ShutdownPipe();
     int GetNext(Record *record);

};

#endif
